import { useUserStore } from '@/stores'
import { showToast } from 'vant'

// 使用ctrl + i 引入这个 Method 这个类型
import axios, { type Method } from 'axios'
import router from '@/router'

// 创建axios实例
const baseURL = 'https://consult-api.itheima.net/'
const instance = axios.create({
  baseURL,
  timeout: 10000
})

// 响应拦截器的配置
instance.interceptors.request.use(
  (config) => {
    // 必须要在这里使用 useUserStore 因为请求时机的问题
    const userStore = useUserStore()
    // ?.可选链操作符
    if (userStore.user?.token) {
      config.headers.Authorization = `Bearer ${userStore.user?.token}`
    }
    // 统一配置请求头
    return config
  },
  (err) => Promise.reject(err)
)

// 请求拦截器的配置
instance.interceptors.response.use(
  // 数据剥壳处理
  // http状态码是200

  // 状态吗是200 但是业务错误, 不是10000(请求成功业务失败)
  (res) => {
    if (res.data?.code !== 10000) {
      showToast(res.data?.message)
      return Promise.reject(res.data)
    }
    return res.data
  },
  // http状态码不是200(网络失败)
  (err) => {
    // 处理 401 的错误
    if (err.response.status === 401) {
      // token 失效
      // 1. 清空token
      const userStore = useUserStore()
      userStore.delUser()
      // 2. 跳转到登录页面
      // 3. router.currentRoute.value.fullPath 代表的是当前的路由地址
      router.push(`/login?returnUrl=${router.currentRoute.value.fullPath}`)
    }
    showToast(err.response.data?.message)
    return Promise.reject(err)
  }
)

// 封装请求工具函数
// 参数
// 返回值 promise
// 类型规定
type Data<T> = {
  code: number
  data: T
  message: string
}
// 我们在使用这个函数的参数传递
// 泛型在函数中的使用
const request = <T>(url: string, method: Method, submitData?: object) => {
  // request 的类型接收三个参数
  // 1. 第一个参数: 代表的是 data
  // 2. 第二个参数: 代表的是 后端的返回值
  // T 代表的是 后端data的 类型
  return instance.request<T, Data<T>>({
    url,
    method,
    // 因为提交的数据是 params 或者 data 所以我们需要根据 method 进行判断到底是哪一个, 因为键名是一个变量,所以我们需要使用[]
    [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
  })
}

export { baseURL, instance, request }
